package com.beyondsoft.test;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Calendar;
import java.util.List;
import java.util.Locale;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ImageFormat;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.YuvImage;
import android.graphics.Paint.Style;
import android.hardware.Camera;
import android.hardware.Camera.Size;
import android.os.Bundle;
import android.text.format.DateFormat;
import android.util.Log;
import android.view.GestureDetector;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.GestureDetector.OnDoubleTapListener;
import android.view.GestureDetector.OnGestureListener;
import android.view.View.OnTouchListener;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.view.View.OnClickListener;

public class CamTrack extends Activity implements OnTouchListener,
		OnGestureListener, OnDoubleTapListener {
	
	private final String TAG = "[SZ]-[CAMERA TRACK]";

	private LinearLayout mMainLayout;
	private FrameLayout mFrameLayout;
	private GestureDetector mGestureDetector;
	private SurfaceView camView;
	private SurfaceHolder camHolder;
	private View mDrawRect = null;
	private View mDrawCircle = null;
	private Camera mCamera = null;
	private Button mBtnExit;
	private Button mBtnStop;

	private boolean mStartTracking = false;
	private boolean mTrackInited = false;
	private float mSelectRect[], mReturnRect[];
	private static final int DLG_EXIT_SYSTEM = 1;
	protected Dialog onCreateDialog(int id) {
		switch (id) {
		case DLG_EXIT_SYSTEM:
			AlertDialog.Builder bdrExit = new AlertDialog.Builder(CamTrack.this);
			bdrExit.setIcon(R.drawable.alert_dialog_icon);
			bdrExit.setTitle(R.string.exit_sytem);
			bdrExit.setPositiveButton(R.string.yes,
					new DialogInterface.OnClickListener() {
						@Override
						public void onClick(DialogInterface dialog, int which) {
							// TODO Auto-generated method stub
							System.exit(0);
						}
					});
			bdrExit.setNegativeButton(R.string.no, null);
			return bdrExit.create();
		}
		return null;
	}
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
        	showDialog(DLG_EXIT_SYSTEM);
            return false;
        }
        return false;
    }
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		/*
		 * Create a TextView and set its content. the text is retrieved by
		 * calling a native function.
		 */

		mMainLayout = (LinearLayout) findViewById(R.id.linearLayout1);
		mFrameLayout = (FrameLayout) findViewById(R.id.frameLayout1);
		mMainLayout.setOnTouchListener(this);
		mMainLayout.setLongClickable(true);
		mGestureDetector = new GestureDetector(this);

		camView = (SurfaceView) findViewById(R.id.surfaceView1);
		camHolder = camView.getHolder();
		camHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
		camHolder.addCallback(new SurfaceHolder.Callback() {
			@Override
			public void surfaceChanged(SurfaceHolder holder, int format,
					int width, int height) {
				// TODO Auto-generated method stub
				Camera.Parameters parameters = mCamera.getParameters();

				// List<Size> sizes = parameters.getSupportedPreviewSizes();
				// Size optimalSize = getOptimalPreviewSize(sizes, width,
				// height);
				// parameters.setPreviewSize(optimalSize.width,
				// optimalSize.height);

				parameters.setPictureFormat(PixelFormat.JPEG);
				parameters.setPictureSize(1024, 768);
				parameters.setPreviewSize(1024, 768);
				// parameters.setPreviewFormat(PixelFormat.)
				mCamera.setPreviewCallback(PreviewCallback);
				mCamera.setParameters(parameters);
				mCamera.startPreview();
			}

			private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
				final double ASPECT_TOLERANCE = 0.05;
				double targetRatio = (double) w / h;
				if (sizes == null)
					return null;

				Size optimalSize = null;
				double minDiff = Double.MAX_VALUE;

				int targetHeight = h;

				// Try to find an size match aspect ratio and size
				for (Size size : sizes) {
					double ratio = (double) size.width / size.height;
					if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)
						continue;
					if (Math.abs(size.height - targetHeight) < minDiff) {
						optimalSize = size;
						minDiff = Math.abs(size.height - targetHeight);
					}
				}

				// Cannot find the one match the aspect ratio, ignore the
				// requirement
				if (optimalSize == null) {
					minDiff = Double.MAX_VALUE;
					for (Size size : sizes) {
						if (Math.abs(size.height - targetHeight) < minDiff) {
							optimalSize = size;
							minDiff = Math.abs(size.height - targetHeight);
						}
					}
				}
				return optimalSize;
			}

			@Override
			public void surfaceCreated(SurfaceHolder holder) {
				// TODO Auto-generated method stub
				mCamera = Camera.open();
				try {
					mCamera.setPreviewDisplay(holder);
				} catch (IOException e) {
					mCamera.release();
					mCamera = null;
				}
			}

			@Override
			public void surfaceDestroyed(SurfaceHolder holder) {
				// TODO Auto-generated method stub
				mCamera.startPreview(); // ֹͣԤ��
				mCamera.stopPreview();
				mCamera.release();
				mCamera = null;
			}
		});

		mBtnStop = (Button) findViewById(R.id.Stop);
		mBtnStop.setOnClickListener(StopTrack);
		
		mBtnExit = (Button) findViewById(R.id.exit);
		mBtnExit.setOnClickListener(ExitSystem);

//		mDrawOvalThd = new Thread() {
//			@Override
//			public void run() {
//			}
//		};
	}

	public void DrawOval() {
		mDrawCircle = new OvalView(this, mReturnRect[0], mReturnRect[1],
				mReturnRect[2], mReturnRect[3]);
		mFrameLayout.addView(mDrawCircle);
		mFrameLayout.postInvalidate();
	}

	public Camera.PreviewCallback PreviewCallback = new Camera.PreviewCallback() {

		@Override
		public void onPreviewFrame(byte[] data, Camera camera) {
			// TODO Auto-generated method stub
//			Log.i(TAG, "onPreviewFrame");
			if (mStartTracking) {
				FileOutputStream outStream = null;
				String fileName;
				try {
					Log.i(TAG, "width:" + camera.getParameters().getPreviewSize().width);
					Log.i(TAG, "height:" + camera.getParameters().getPreviewSize().height);
					
					YuvImage yuvimage = new YuvImage(data, ImageFormat.NV21,
							camera.getParameters().getPreviewSize().width,//
							camera.getParameters().getPreviewSize().height,//
							null);
					ByteArrayOutputStream baos = new ByteArrayOutputStream();
					yuvimage.compressToJpeg(new Rect(0, 0, 
							camera.getParameters().getPreviewSize().width, 
							camera.getParameters().getPreviewSize().height
							), 80, baos);

					fileName = "/mnt/sdcard/CamTrackCache/pic_"
							+ DateFormat.format("yyyyMMdd_hhmmss",
									Calendar.getInstance(Locale.CHINA))
							+ ".jpg";

					outStream = new FileOutputStream(fileName);
					outStream.write(baos.toByteArray());
					outStream.close();

					if (!mTrackInited) {
						NativeCall.TrackInit(fileName, mSelectRect);
						mTrackInited = true;
					}
					mReturnRect = NativeCall.GetTrackRange(fileName);
					
					if (null != mDrawRect) {
						mFrameLayout.removeView(mDrawRect);
						mFrameLayout.postInvalidate();
						mDrawRect = null;
					}
					if (null != mDrawCircle) {
						mFrameLayout.removeView(mDrawCircle);
						mFrameLayout.postInvalidate();
						mDrawCircle = null;
					}
					DrawOval();
					File f = new File(fileName);
					if (f.exists()) {
						f.delete();
					}
				} catch (FileNotFoundException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	};
	private OnClickListener StopTrack = new OnClickListener() {

		@Override
		public void onClick(View v) {
			// TODO Auto-generated method stub
			if (null != mDrawCircle) {
				mFrameLayout.removeView(mDrawCircle);
				mFrameLayout.postInvalidate();
				mDrawCircle = null;
			}
			mTrackInited = false;
			mStartTracking = false;
		}
	};
	private OnClickListener ExitSystem = new OnClickListener() {
		public void onClick(View v) {
			showDialog(DLG_EXIT_SYSTEM);
			// System.exit(0);
		}
	};

	@Override
	public boolean onDoubleTap(MotionEvent e) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean onDoubleTapEvent(MotionEvent e) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean onSingleTapConfirmed(MotionEvent e) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean onDown(MotionEvent e) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
			float velocityY) {
		// TODO Auto-generated method stub
		Log.i(TAG, "onFling!");
		Log.i(TAG, "Begin X: " + e1.getX());
		Log.i(TAG, "Begin y: " + e1.getY());
		Log.i(TAG, "End X: " + e2.getX());
		Log.i(TAG, "End Y: " + e2.getY());

		mSelectRect = new float[4];
		mSelectRect[0] = Math.min(e1.getX(), e2.getX());
		mSelectRect[1] = Math.min(e1.getY(), e2.getY());
		mSelectRect[2] = Math.max(e1.getX(), e2.getX());
		mSelectRect[3] = Math.max(e1.getY(), e2.getY());

		Log.i(TAG, String.valueOf(mSelectRect[0]));
		Log.i(TAG, String.valueOf(mSelectRect[1]));
		Log.i(TAG, String.valueOf(mSelectRect[2]));
		Log.i(TAG, String.valueOf(mSelectRect[3]));
		mStartTracking = true;
		return false;
	}

	@Override
	public void onLongPress(MotionEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
			float distanceY) {
		// TODO Auto-generated method stub
		Log.i(TAG, "onScroll!");
		if (null != mDrawRect) {
			mFrameLayout.removeView(mDrawRect);
			mDrawRect = null;
		}

		mDrawRect = new RectView(this, e1.getX(), e1.getY(), e2.getX(),	e2.getY());
		mFrameLayout.addView(mDrawRect);
		mFrameLayout.postInvalidate();

		return false;
	}

	@Override
	public void onShowPress(MotionEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public boolean onSingleTapUp(MotionEvent e) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean onTouch(View view, MotionEvent event) {
		// TODO Auto-generated method stub
		return mGestureDetector.onTouchEvent(event);
	}
}

class RectView extends View {
	float mStartX, mStartY, mEndX, mEndY;
	Paint mPaint;

	RectView(Context context, float startX, float startY, float endX, float endY) {
		super(context);
		mStartX = startX;
		mStartY = startY;
		mEndX = endX;
		mEndY = endY;
		
		mPaint = new Paint();
	}

	@Override
	public void onDraw(Canvas canvas) {

		canvas.save();
//		Paint mPaint = new Paint();
		mPaint.setStyle(Style.STROKE);
		mPaint.setColor(Color.GREEN);
		mPaint.setStrokeWidth(2);
		canvas.drawRect(mStartX, mStartY, mEndX, mEndY, mPaint);
	}
}

class OvalView extends View {
	float mStartX, mStartY, mEndX, mEndY;
	Paint mPaint;

	OvalView(Context context, float startX, float startY, float endX, float endY) {
		super(context);
		mStartX = startX;
		mStartY = startY;
		mEndX = endX;
		mEndY = endY;
		
		mPaint = new Paint();
	}

	@Override
	public void onDraw(Canvas canvas) {
		canvas.save();
//		Paint mPaint = new Paint();
		mPaint.setStyle(Style.STROKE);
		mPaint.setColor(Color.GREEN);
		mPaint.setStrokeWidth(2);
		canvas.drawOval(new RectF(mStartX, mStartY, mEndX, mEndY), mPaint);
	}
}
